package bxpay

import (
	"context"
	"crypto"
	"crypto/md5"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"sort"
	"strings"

	"gitee.com/liuxuezhan/ar-platform/assets-api/internal/pay/base"
)

type Factory struct {
}

func (p *Factory) CreatePay(config base.Config) base.Payment {
	return &BXPay{
		Url:        config.Url,
		MerchantId: config.MerchantId,
		SecretKey:  config.SecretKey,
		PrivateKey: config.PrivateKey,
	}
}

// Response represents the structure of the response from the API
type Response struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Time string `json:"time"`
	Data struct {
		PayUrl     string `json:"payurl"`
		OrderNo    string `json:"orderno"`
		SysOrderNo string `json:"sysorderno"`
	} `json:"data"`
}

type BXPay struct {
	Url        string `json:"url"`         // 网关//
	MerchantId string `json:"merchant_id"` // 商户账号
	SecretKey  string `json:"secret_key"`  // 代收秘钥
	PrivateKey string `json:"private_key"`
}

func (t *BXPay) Pay(ctx context.Context, params map[string]interface{}) (base.PayResponse, error) {
	amount, ok := params["amount"].(float64)
	if !ok {
		return base.PayResponse{}, fmt.Errorf("amount type invalid")
	}
	data := map[string]interface{}{
		"merId":    t.MerchantId,                // 商户号
		"orderId":  params["orderNo"],           // 订单号
		"orderAmt": fmt.Sprintf("%.2f", amount), // 交易金额
		"channel":  params["name"],              // 通道类型
		"desc":     "recharge",                  // 订单描述
		// "attch":    "AES",  //附加信息
		// "smstyle":  "1.0",  //扫码模式
		// "userId":    params["user_id"],   //用户编号
		"ip":        params["ip"],        // 下单ip地址
		"notifyUrl": params["notifyUrl"], // 通知地址
		"returnUrl": params["returnUrl"], // 页面跳转地址
		"nonceStr":  params["nonceStr"],  // 随机字符串
	}

	sign, err := t.RechargeSign(data)
	if err != nil {
		return base.PayResponse{}, err
	}
	data["sign"] = sign
	fmt.Println("params---\n", data)
	pubKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAknMVNmbAEkqISwfSju8m3VdDmVRGtM4umYQLaf09dgQ2WHFz2kxH8oJdcpXBjJAcktLKEzWaPAr31MM38lsyxFrtdv8nhJ6PGMwtC4kBPEoW7k5SLDsaxB4gZkMjr96XSYKXF9tUILHd0XNqWJLx89e6rgyD6DBOTPScl0qUliu4Hu0eoWODOvAfWmJuHb2o6xunn3Lg1ZE6Memw9zrf1SbSJ/+EwjU+kegwx/LEkLWoWEtal0r38uOrjaPsqmwqug5R7auAJ8NLoDX/ZbEr3q9Rm3SdzCgFsOnplNEU4hxoSsqfuMstgGDU8cLEgm1uAdqcO4IeMlBj7z65XjyaDQIDAQAB"
	pubKey = "-----BEGIN PUBLIC KEY-----\n" + pubKey + "\n-----END PUBLIC KEY-----"

	if err != nil {
		return base.PayResponse{}, err
	}

	payUrl := t.Url + "/pay"
	response, err := t.send(ctx, payUrl, data)
	if err != nil {
		return base.PayResponse{}, err
	}

	return base.PayResponse{
		Url:     response.Data.PayUrl,
		Address: "",
		OrderNo: response.Data.OrderNo,
	}, nil
}

func (t *BXPay) RechargeSign(data map[string]interface{}) (string, error) {
	return t.sign(data, t.SecretKey)
}

// 发送请求，处理返回数据
func (t *BXPay) send(ctx context.Context, payUrl string, data map[string]interface{}) (Response, error) {
	resp, err := base.SendPostJson(ctx, payUrl, data)
	if err != nil {
		return Response{}, err
	}

	// Parse the JSON response
	var response Response
	err = json.Unmarshal([]byte(resp), &response)
	if err != nil {
		return Response{}, err
	}

	// 返回结果处理
	if response.Code != 200 {
		return Response{}, errors.New(response.Msg)
	}

	return response, nil
}

func (t *BXPay) sign(data map[string]interface{}, secret string) (string, error) {
	// 1. 将接口中的请求字段按照 ASCII 码方式进行升序排序
	var sortKeys []string
	for key := range data {
		sortKeys = append(sortKeys, key)
	}
	sort.Strings(sortKeys) // 对 key 进行排序

	// 2. 按照 key1=val1&key2=val2&key3=val3....&key=md5秘钥生成加密字符串
	var sb strings.Builder
	for _, k := range sortKeys {
		sb.WriteString(fmt.Sprintf("%s=%v&", k, data[k]))
	}
	sb.WriteString(fmt.Sprintf("key=%s", secret))
	str := sb.String()

	// 3: MD5 hash the string and convert to uppercase
	hash := md5.Sum([]byte(str))

	md5Str := hex.EncodeToString(hash[:])

	md5Str = strings.ToUpper(md5Str)
	fmt.Println("md5---\n", md5Str)
	// 将 md5Str 从字符串转换为字节切片
	messageHash, err := hex.DecodeString(md5Str)
	if err != nil {
		return "", fmt.Errorf("failed to decode MD5 hash: %v", err)
	}

	privateKey := "-----BEGIN RSA PRIVATE KEY-----\n" + t.PrivateKey + "\n-----END RSA PRIVATE KEY-----\n"

	// 4: RSA sign the hash
	block, _ := pem.Decode([]byte(privateKey))
	if block == nil || block.Type != "RSA PRIVATE KEY" {
		return "", fmt.Errorf("failed to decode private key")
	}

	private, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return "", fmt.Errorf("failed to parse private key: %v", err)
	}

	// 使用 messageHash 作为原始消息的哈希值进行签名
	signature, err := rsa.SignPKCS1v15(rand.Reader, private.(*rsa.PrivateKey), crypto.MD5, messageHash)
	if err != nil {
		return "", fmt.Errorf("failed to sign: %v", err)
	}

	return base64.StdEncoding.EncodeToString(signature), nil
}
